﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using UC_Framework;

namespace SwarmPlay
{
    static class SpidersMover
    {
        public static float TurnAbit(float origAngle, float destAngle, float dRate, out float turn)
        {
            float absdiff = Math.Abs(origAngle - destAngle);
            if (absdiff > Math.PI)
            {
                if (destAngle > origAngle)
                {
                    float diff = origAngle - destAngle + (float)Math.PI * 2;
                    turn = dRate * diff;
                    return origAngle - turn;
                }
                else
                {
                    float diff = destAngle - origAngle +(float)Math.PI * 2;
                    turn = dRate * diff;
                    return origAngle + turn;
                }
            }
            else
            {
                if (destAngle > origAngle)
                {
                    float diff = destAngle - origAngle;
                    turn = dRate * diff;
                    return origAngle + turn;
                }
                else
                {
                    float diff = origAngle - destAngle;
                    turn = dRate * diff;
                    return origAngle - turn;
                }
            }
        }

        public static void PickBug(this GameLevel_3 game, Sprite2 spider, Sprite2 bug,
            GameTime gameTime, float inactiveRate)
        {
            Random rand = new Random();

            Vector2 pos = spider.getPos();

            // change the speed or angle every 20 ticks
            if (gameTime.TotalGameTime.Ticks % 20 == 0)
            {
                Vector2 bugPos = bug.getPos();
                Vector2 aim = bugPos - pos;

                float turned = 0;
                if (aim.Length() > 0)
                {
                    float oldAngle = spider.getMoveAngle();

                    float destAngle = (float)Math.Atan2(aim.Y, aim.X);
                    float angle = 0;
                    angle = TurnAbit(oldAngle, destAngle, (float)Math.PI * 0.1f, out turned);

                    spider.setMoveAngle(angle);
                    spider.setDisplayAngle(angle);
                }

                if (turned <= Math.PI * 0.2)
                {
                    // spiders speed ranges from zero to 2 times the speed of swarm
                    float speed = game.swarmSpeed * 0.5f + 
                        rand.Next(100) * game.swarmSpeed * 0.02f * (1 - inactiveRate);
                    spider.setMoveSpeed(speed);
                }
            }
            spider.moveByAngleSpeed(true);
        }

        public static void MoveSingleSpider(this GameLevel_3 game, Sprite2 spider,
            GameTime gameTime, ref float inactiveRate)
        {
            Vector2 pos = spider.getPos();
            Sprite2 nearestBug = null;
            float nearestBugDist = float.PositiveInfinity;
            for (int i = 0; i < game.numSprites; i++)
            {
                Sprite2 bug = game.sl.getSprite(i);
                if (bug == null) continue;

                Vector2 bugPos = bug.getPos();
                float dist = (bugPos - pos).Length();
                if (dist < nearestBugDist)
                {
                    nearestBugDist = dist;
                    nearestBug = bug;
                }
            }

            if (nearestBug != null)
            {
                PickBug(game, spider, nearestBug, gameTime, inactiveRate);
            }

            SwarmMover.AvoidObstacles(game, spider, 1f, 1f);

        }

        public static void CheckWithSwarm(this GameLevel_3 game, Sprite2 spider, ref float inactiveRate)
        {
            for (int i = 0; i < game.numSprites; i++ )
            {
                Sprite2 bug = game.sl.getSprite(i);

                if (bug == null) continue;

                Vector2 distVec = bug.getPos() - spider.getPos();
                bool toEat = distVec.Length() < spider.getTexture().Bounds.Width * 0.3f;
                float angle = spider.getDisplayAngle();
                Vector2 aimVec = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));

                Vector2 distVecNormed = distVec;
                distVecNormed.Normalize();
                float cosD = distVecNormed.X * aimVec.X + distVecNormed.Y * aimVec.Y;

                toEat = toEat && cosD > 0.70f;
                if (toEat)
                {
                    game.sl.deleteSprite(i);
                    if (inactiveRate < 0.5f)
                    {
                        inactiveRate = 8.0f;
                    }
                    else
                    {
                        inactiveRate = inactiveRate * 1.1f;
                        if (inactiveRate > 1) inactiveRate = 1;
                    }
                }
            }
        }

        public static void MoveSpiders(this GameLevel_3 game, GameTime gameTime)
        {
            
            for (int i = 0; i < game.numSpiders; i++)
            {
                Sprite2 spider = game.spiders.getSprite(i);

                float inactiveRate = game.inactiveList[i];

                if (inactiveRate < 0.8f)
                {
                    CheckWithSwarm(game, spider, ref inactiveRate);
                    MoveSingleSpider(game, spider, gameTime, ref inactiveRate);
                }
                inactiveRate *= 0.9f;
                game.inactiveList[i] = inactiveRate;
            }
        }
    }
}